﻿using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;
using LFSRecord2.Model.Media;
using LFSRecord2.Model;
using System.Windows.Input;
using LFSRecord2.Events;
using LFSRecord2.Model.UserActions;

namespace LFSRecord2.View.TimelineStructures
{
    /// <summary>
    /// Interaction logic for TimelineAudioLayerDataView.xaml
    /// </summary>
    public partial class TimelineAudioLayerDataView : UserControl
    {
        public TimelineAudioLayerDataView()
        {
            InitializeComponent();
        }

        private void UserControl_DragEnter(object sender, DragEventArgs e)
        {
            if (!canAcceptDropItem(e.Data))
            {
                e.Effects = DragDropEffects.None;
                e.Handled = true;
            }
            else
            {
                char splitChar = (char)124;
                string[] info = ((string)e.Data.GetData(DataFormats.Text)).Split(splitChar);

                int mediaIndex = LfsRecordController.project.HasMediaFile(info[1]);
                if (mediaIndex == -1)
                    return;

                MediaAudio ma = (MediaAudio)LfsRecordController.project.MediaObjects[mediaIndex];
                Point curPos = e.GetPosition(this);
                DropPreviewRange.Width = ma.AudioStream.Duration * LfsRecordController.project.FPS;
                DropPreviewRange.Margin = new Thickness(curPos.X, 0, 0, 1);
                DropPreviewRange.Visibility = Visibility.Visible;
            }
        }

        private void UserControl_DragOver(object sender, DragEventArgs e)
        {
            if (!canAcceptDropItem(e.Data))
            {
                e.Effects = DragDropEffects.None;
                e.Handled = true;
            }
            else
            {
                Point curPos = e.GetPosition(this);
                DropPreviewRange.Margin = new Thickness(curPos.X, 0, 0, 1);
            }
        }

        private void UserControl_DragLeave(object sender, DragEventArgs e)
        {
            // Clear possible media object area ghost preview
            //Debug.WriteLine("dragleave");
            DropPreviewRange.Visibility = Visibility.Collapsed;
        }

        private void UserControl_Drop(object sender, DragEventArgs e)
        {
            IDataObject data = e.Data;

            if (canAcceptDropItem(e.Data))
            {
                char splitChar = (char)124;
                string[] info = ((string)data.GetData(DataFormats.Text)).Split(splitChar);

                if (info.Length == 2 && info[0] == "MediaAudio")
                {
                    Point curPos = e.GetPosition(this);
                    //Debug.WriteLine("CurX : {0}", curPos.X);

                    // Drop item into place (add it to the audio track)
                    int mediaIndex = LfsRecordController.project.HasMediaFile(info[1]);
                    if (mediaIndex > -1)
                    {
                        MediaAudio ma = (MediaAudio)LfsRecordController.project.MediaObjects[mediaIndex];
                        AudioLayer l = (AudioLayer)DataContext;
                        AudioRegion ar = l.AddRegion(mediaIndex, ma, curPos.X / LfsRecordController.project.FPS);

                        ar.PlaybackPtr = (long)(((LfsRecordController.FrameIndex / (double)LfsRecordController.project.FPS) - ar.TimeOffset) * (ar.AudioStream.Format.nBlockAlign * LfsRecordController.Mixer.SampleRate));
                        ar.PlaybackPtr -= ar.PlaybackPtr % ar.AudioStream.Format.nBlockAlign;

                        LfsRecordController.project.DeselectAll();
                        ar.IsSelected = true;
                        l.IsSelected = true;

                        LfsRecordController.RecordUserAction(new UserActionAddAudioRegion()
                        {
                            LayerIndex = l.LayerIndex,
                            RegionData = ar.DataStructure()
                        });
                        LfsRecordController.CreateUndoLevel();
                    }
                }
            }

            DropPreviewRange.Visibility = Visibility.Collapsed;
        }

        private bool canAcceptDropItem(IDataObject data)
        {
            if (!data.GetDataPresent(DataFormats.Text))
            {
                return false;
            }
            else
            {
                char splitChar = (char)124;
                string[] info = ((string)data.GetData(DataFormats.Text)).Split(splitChar);

                if (info.Length != 2 || info[0] != "MediaAudio")
                {
                    return false;
                }
            }
            return true;
        }

        private void Grid_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            e.Handled = true;
            LfsRecordController.project.DeselectAll();
            ((AudioLayer)DataContext).IsSelected = true;
        }

        Point _startPoint;
        double _origLeftMargin;
        double _objectHasMoved;
        AudioRegionControl _dragControl;
        private void AudioRegionControl_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            e.Handled = true;

            _objectHasMoved = 0;
            _startPoint = e.GetPosition(RegionCanvas);
            _dragControl = (AudioRegionControl)sender;
            _origLeftMargin = _dragControl.Margin.Left;

            AudioRegion ar = (AudioRegion)_dragControl.DataContext;
            if (!ar.IsSelected)
            {
                if (!Keyboard.IsKeyDown(Key.LeftShift) && !Keyboard.IsKeyDown(Key.RightShift))
                    LfsRecordController.project.DeselectAll();
                ar.IsSelected = true;
                ar.ParentLayer.IsSelected = true;
            }
            else
            {
                if (Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift))
                {
                    ar.IsSelected = false;
                }
            }

            Application.Current.MainWindow.MouseUp += AudioRegionControl_MouseLeftButtonUp;
            Application.Current.MainWindow.MouseMove += AudioRegionControl_MouseMove;
        }

        private void AudioRegionControl_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            e.Handled = true;

            Application.Current.MainWindow.MouseUp -= AudioRegionControl_MouseLeftButtonUp;
            Application.Current.MainWindow.MouseMove -= AudioRegionControl_MouseMove;

            // undo
            if (_objectHasMoved != 0)
            {
                LfsRecordController.project.DeleteOverlappingKeyFrames();

                LfsRecordController.project.SubmitUserActionMoveSelectedKeyFrames((int)_objectHasMoved);
                LfsRecordController.project.SubmitUserActionMoveSelectedAudioRegions(_objectHasMoved / LfsRecordController.project.FPS);
                LfsRecordController.CreateUndoLevel();
            }

            _dragControl = null;
        }

        private void AudioRegionControl_MouseMove(object sender, MouseEventArgs e)
        {
            // Calculate the move offset
            Point curPoint = e.GetPosition(RegionCanvas);
            Point diff = new Point(curPoint.X - _startPoint.X, curPoint.Y - _startPoint.Y);

            // Get the x offset of the first selected KeyFrame
            double moveOffset = diff.X;
            if (moveOffset == 0)
                return;

            int firstFrameNum = LfsRecordController.project.GetFirstSelectedFrameNum();
            //Debug.WriteLine("Firstselected framenum : {0}", firstFrameNum);
            if (moveOffset < 0)
            {
                if (firstFrameNum <= 0)
                    return;
                if (firstFrameNum + moveOffset < 0)
                    moveOffset = -firstFrameNum;
            }
            _objectHasMoved += moveOffset;

            //AudioRegion ar = (AudioRegion)_dragControl.DataContext;
            LfsRecordController.project.MoveSelectedAudioRegions(moveOffset / LfsRecordController.project.FPS);
            
            LfsRecordController.project.MoveSelectedKeyFrames((int)moveOffset);
            ServicesFactory.EventService.GetEvent<CompLayerPropertyChangedEvent>().Publish(new CompLayerPropertyChangedEventArgs()
            {
                Sender = this,
                PropertyType = "FrameNum",
                UpdateCurrentValues = true
            });

            _startPoint = curPoint;
        }
    }
}
